目前为止，大多数代码示例都假设内核函数的每个实例对应于单个数据块上的单个操作。这是编写内核的一个简单方法，但这种数据与工作项的一一映射不是由DPC++全控制的，所以使得任务参数化是提高应用性能和可移植性的好方法。\par

\hspace*{\fill} \par %插入空行
\textbf{一对一映射}

当编写与工作项的一一映射的内核时，这些内核需要完成的工作量必须适配range或nd\_range的大小。这是编写内核的最简单的方式，这种方式工作得非常好——可以信底层任实现工作项映射到硬件。\par

然而，对系统和实现的特定组合进行性能调优时，需要更加注意底层调度。工作组对计算资源的调度由实现定义，并且可能是动态的(例如，当一个计算资源完成一个工作组时，执行的下一个工作组可能来自于共享队列)。动态调度对性能的影响不确定，其重要性取决于内核函数每个实例的执行时间，以及调度软件(如CPU)或硬件(如GPU)上的实现。\par

\hspace*{\fill} \par %插入空行
\textbf{多对一映射}

另一种方法是编写多对一映射的内核，range的含义略有变化:不再描述要完成的工作量，而是要使用的工作项的数量。通过改变工作项的数量和分配给每个工作项的工作量，可以调整工作分配，以最大限度地提高效率。\par

编写这种形式的内核需要做两个更改:\par

\begin{itemize}
	\item 内核必须接受描述工作总量的参数。
	\item 内核必须包含将工作分配给工作项的循环。
\end{itemize}

图4-25给出了这样的内核示例，内部的循环稍微不同寻常——起始索引是全局范围内工作项的索引，而跨距是工作项的总数。这种数据到工作项的循环调度确保了循环的所有N次迭代将由一个工作项执行，而且线性工作项可以访问连续的内存位置(以改进缓存局部性和向量化行为)。工作可以分布在多个工作组或单个工作组中的工作项中，以进一步利用局部性。\par

\hspace*{\fill} \par %插入空行
图4-25 具有独立数据和执行范围的内核
\begin{lstlisting}[caption={}]
size_t N = ...; // amount of work
size_t W = ...; // number of workers
h.parallel_for(range{W}, [=](item<1> it) {
	for (int i = it.get_id()[0]; i < N; i += it.get_range()[0]) {
		output[i] = function(input[i]);
	}
});
\end{lstlisting}

这些分发模式很常见，使用具有逻辑范围的分层并行时，可以使用。我们期望未来的DPC++引入语法糖，来简化ND-Range内核中分发模式的表示。\par


































